﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using S7.Net;
using S7PlcDataManager.S7Plc.Types;
using S7PlcDataManager.Tools;
using ZbSkin.Tools;

namespace S7PlcDataManager.Controls
{
    public partial class DataTypeControl : UserControl
    {
        public event Action DataTypeChanged = () => { };

        public string Variable => tb_variable.Text.Trim();
        public VarType ValueType => (VarType)cmb_val.SelectedItem;

        public DataTypeControl()
        {
            InitializeComponent();
        }

        private void DataTypeControl_Load(object sender, EventArgs e)
        {
            var valTypeList = Enum.GetValues(typeof(VarType));
            cmb_val.DataSource = valTypeList;

            var plcDataTypeList = GetPlcDataTypeList();
            cmb_datatype.DataSource = plcDataTypeList;
            cmb_datatype.DisplayMember = @"TypeString";

            SetRegion();
        }

        #region GetPlcDataTypeList

        private static List<PlcDataType> GetPlcDataTypeList()
        {
            return new List<PlcDataType>
            {
                GetBlockDataType(),
                GetInputDataType(),
                GetOutputDataType(),
                GetMemoryDataType()
            };
        }

        private static PlcDataType GetBlockDataType()
        {
            return new PlcDataType
            {
                TypeString = Constants.PlcDataType.DataBlock,
                ValTypeList = new List<PlcValType>()
                {
                    new PlcValType {Type = VarType.Byte, TypeString = @"DBB"},
                    new PlcValType {Type = VarType.Word, TypeString = @"DBW"},
                    new PlcValType {Type = VarType.DWord, TypeString = @"DBD"},
                    new PlcValType {Type = VarType.Bit, TypeString = @"DBX"},
                }
            };
        }

        private static PlcDataType GetInputDataType()
        {
            return new PlcDataType
            {
                TypeString = Constants.PlcDataType.Input,
                ValTypeList = new List<PlcValType>()
                {
                    new PlcValType {Type = VarType.Byte, TypeString = @"IB"},
                    new PlcValType {Type = VarType.Word, TypeString = @"IW"},
                    new PlcValType {Type = VarType.DWord, TypeString = @"ID"},
                    new PlcValType {Type = VarType.Bit, TypeString = @"I"}
                }
            };
        }

        private static PlcDataType GetOutputDataType()
        {
            return new PlcDataType
            {
                TypeString = Constants.PlcDataType.Output,
                ValTypeList = new List<PlcValType>()
                {
                    new PlcValType {Type = VarType.Byte, TypeString = @"QB"},
                    new PlcValType {Type = VarType.Word, TypeString = @"QW"},
                    new PlcValType {Type = VarType.DWord, TypeString = @"QD"},
                    new PlcValType {Type = VarType.Bit, TypeString = @"Q"}
                }
            };
        }

        private static PlcDataType GetMemoryDataType()
        {
            return new PlcDataType
            {
                TypeString = Constants.PlcDataType.Memory,
                ValTypeList = new List<PlcValType>()
                {
                    new PlcValType {Type = VarType.Byte, TypeString = @"MB"},
                    new PlcValType {Type = VarType.Word, TypeString = @"MW"},
                    new PlcValType {Type = VarType.DWord, TypeString = @"MD"},
                    new PlcValType {Type = VarType.Bit, TypeString = @"M"}
                }
            };
        }

        #endregion

        private void DataTypeControl_Resize(object sender, EventArgs e)
        {
            SetRegion();
        }

        private void SetRegion()
        {
            this.SetRegion(30);
        }

        #region SelectedIndexChanged

        // ReSharper disable once IdentifierTypo
        private void cmb_datatype_SelectedValueChanged(object sender, EventArgs e)
        {
            var plcDataType = cmb_datatype.SelectedItem as PlcDataType;
            cmb_valtype.DataSource = plcDataType?.ValTypeList;
            cmb_valtype.DisplayMember = @"TypeString";
        }

        // ReSharper disable once IdentifierTypo
        private void cmb_valtype_SelectedIndexChanged(object sender, EventArgs e)
        {
            var plcValType = cmb_valtype.SelectedItem as PlcValType;
            cmb_val.SelectedItem = plcValType?.Type;

            var plcValTypeString = plcValType?.TypeString;
            var plcDataTypeString = (cmb_datatype.SelectedItem as PlcDataType)?.TypeString;
            var enableTextBoxVariable = true;
            if (plcDataTypeString != Constants.PlcDataType.DataBlock)
            {
                enableTextBoxVariable = plcValTypeString == @"I" ||
                                        plcValTypeString == @"Q" ||
                                        plcValTypeString == @"M";
            }

            tb_offset2.Enabled = enableTextBoxVariable;

            UpdateVariable();
        }

        private void cmb_val_SelectedValueChanged(object sender, EventArgs e)
        {
            DataTypeChanged?.Invoke();
        }

        #endregion

        private void tb_offset_TextChanged(object sender, EventArgs e)
        {
            UpdateVariable();
        }

        private void UpdateVariable()
        {
            var offset1 = tb_offset1.Text.Trim();
            var offset2 = tb_offset2.Text.Trim();
            var plcValTypeString = (cmb_valtype.SelectedItem as PlcValType)?.TypeString;
            var plcDataTypeString = (cmb_datatype.SelectedItem as PlcDataType)?.TypeString;
            if (plcDataTypeString == Constants.PlcDataType.DataBlock)
            {
                //DB1.DBD40
                tb_variable.Text = $@"DB{offset1}.{plcValTypeString}{offset2}";
            }
            else if (plcDataTypeString == Constants.PlcDataType.Input)
            {
                //I2000.1, IB200
                tb_variable.Text = plcValTypeString == @"I"
                    ? $@"{plcValTypeString}{offset1}.{offset2}"
                    : $@"{plcValTypeString}{offset1}";
            }
            else if (plcDataTypeString == Constants.PlcDataType.Output)
            {
                //Q2000.1, QB200
                tb_variable.Text = plcValTypeString == @"Q"
                    ? $@"{plcValTypeString}{offset1}.{offset2}"
                    : $@"{plcValTypeString}{offset1}";
            }
            else if (plcDataTypeString == Constants.PlcDataType.Memory)
            {
                //M2000.1, MB200
                tb_variable.Text = plcValTypeString == @"M"
                    ? $@"{plcValTypeString}{offset1}.{offset2}"
                    : $@"{plcValTypeString}{offset1}";
            }

            DataTypeChanged?.Invoke();
        }
    }
}
